package app

import (
	"context"
	"sync"
	"time"

	"torler.com/qingyue/apps/backend/config"
	"torler.com/qingyue/apps/backend/internal/app/core"
	"torler.com/qingyue/apps/backend/internal/service"
	"torler.com/qingyue/apps/backend/internal/store"
	"torler.com/qingyue/apps/backend/internal/transport/http/api"
	"torler.com/qingyue/apps/backend/internal/transport/http/handler"
	"torler.com/qingyue/pkg/logger"
	"torler.com/qingyue/pkg/runtime"
	"torler.com/qingyue/pkg/storage"
)

type Application struct {
	Container *core.Container // 应用容器，用于存放公共组件

	RumtimeMgr *runtime.RuntimeManager // 服务管理
	ApiMgr     *api.ApiManager         //Api管理
	Storeage   *store.StoreManager     //存储管理
	HandlerMgr *handler.HandlerManager //handler管理
	ServiceMgr *service.ServiceManager //service管理
	// 状态
	mu        sync.RWMutex
	startTime time.Time
	ready     bool
}

func NewApp(name string, cfg *config.Config) *Application {
	container := core.NewContainer(cfg, logger.Module("app"))
	storage := store.NewStoreManager(container)
	serviceMgr := service.NewServiceManager(container, storage)
	handlerMgr := handler.NewHandlerManager(container, serviceMgr)
	app := &Application{
		RumtimeMgr: runtime.NewServer(name),
		ServiceMgr: serviceMgr,
		ApiMgr:     api.NewApiManager(cfg.HTTP, handlerMgr),
		HandlerMgr: handlerMgr,
		Container:  container,
		Storeage:   storage,
	}

	app.startTime = time.Now()
	app.ready = false

	return app
}

func (app *Application) Init() error {
	app.mu.Lock()
	defer app.mu.Unlock()

	if app.ready {
		return nil
	}
	if err := app.initDatabase(); err != nil {
		return err
	}

	if err := app.initRedis(); err != nil {
		return err
	}
	app.ServiceMgr.Init()
	app.HandlerMgr.Init()
	app.ApiMgr.Init()
	app.Container.Logger.Info("应用初始化完成")
	app.ready = true
	return nil
}
func (app *Application) initDatabase() error {
	dbConfig := app.Container.Config.DB
	database := storage.NewDatabase(dbConfig)
	database.Connect()
	app.Container.DB = database.DB
	return nil
}

func (app *Application) Run() error {
	err := app.RumtimeMgr.Run(context.Background())
	if err != nil {
		return err
	}
	return nil
}
func (app *Application) AddServer(server runtime.Server) {
	app.RumtimeMgr.Add(server)
}
func (app *Application) initRedis() error {
	config := app.Container.Config.Redis
	client := storage.NewRedis(config)
	app.Container.R = client
	return nil
}
